package com.zhp.utils;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author zhanghp
 * @since 2024/5/14 14:19
 */
public class EnumUtils {


    /**
     * 获取枚举，指定字段及值映射的结果集
     *
     * @param enumClass  自定义枚举
     * @param fieldNames 字段名称
     * @param <T>        泛型
     * @return 字段-值，映射集
     */
    public static <T extends Enum<T>> List<Map<Object, Object>> getEnum(Class<T> enumClass, String... fieldNames) {
        List<Map<Object, Object>> ans = new ArrayList<>();
        if (enumClass == null || ArrayUtil.isEmpty(fieldNames)) {
            Console.log("enumClass is null or fields arrays is empty");
            return ans;
        }
        try {
            for (T enumConstant : enumClass.getEnumConstants()) {
                Map<Object, Object> map = new HashMap<>();
                for (String fieldName : fieldNames) {
                    Field field = enumClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    map.put(fieldName, field.get(enumConstant));
                }
                ans.add(map);
                return ans;
            }
        } catch (Exception e) {
            Console.error(e);
        }
        return ListUtil.empty();
    }

    /**
     * 获取枚举，指定字段的所有值
     *
     * @param enumClass 自定义枚举
     * @param fieldName 字段名称
     * @param <T>       泛型
     * @return 字段值列表
     */
    public static <T extends Enum<T>> List<Object> valsByField(Class<T> enumClass, String fieldName) {
        List<Object> ans = new ArrayList<>();
        if (enumClass == null || StrUtil.isBlank(fieldName)) {
            Console.log("enumClass is null or fieldName is empty");
            return ans;
        }
        try {
            for (T enumConstant : enumClass.getEnumConstants()) {
                Field field = enumClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                ans.add(field.get(enumConstant));
                return ans;
            }
        } catch (Exception e) {
            Console.error(e);
        }
        return ListUtil.empty();
    }

    /**
     * 通过指定字段名和对应值，获取对应的枚举
     *
     * @param enumClass  自定义枚举
     * @param fieldName  字段名称
     * @param fieldValue 字段值
     * @param <T>        泛型
     * @return 枚举
     */
    public static <T extends Enum<T>> T enumByField(Class<T> enumClass, String fieldName, Object fieldValue) {
        T ans = null;
        if (enumClass == null || StrUtil.isBlank(fieldName) || fieldValue == null) {
            Console.log("[enumClass is null] or [fieldName or fieldValue is empty]");
            return ans;
        }
        try {
            for (T enumConstant : enumClass.getEnumConstants()) {
                Field field = enumClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                Object value = field.get(enumConstant);
                if (Objects.equals(value, fieldValue)) {
                    return enumConstant;
                }
            }
        } catch (Exception e) {
            Console.error(e);
        }
        return null;
    }

    /**
     * 通过指定字段名和对应值，获取目标字段值
     *
     * @param enumClass       自定义枚举
     * @param sourceFieldName 值字段名称
     * @param targetFieldName 目标字段名称
     * @param sourceFieldVal  目标字段值
     * @param <E>
     * @return
     */
    public static <E extends Enum<E>> Object valBySourceField(Class<E> enumClass, String sourceFieldName, Object sourceFieldVal, String targetFieldName) {
        try {
            E[] enumConstants = enumClass.getEnumConstants();
            for (E enumConstant : enumConstants) {
                Field valueField = enumClass.getDeclaredField(sourceFieldName);
                valueField.setAccessible(true);
                Object value = valueField.get(enumConstant);
                if (Objects.equals(value, sourceFieldVal)) {
                    Field targetField = enumClass.getDeclaredField(targetFieldName);
                    targetField.setAccessible(true);
                    return targetField.get(enumConstant);
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            Console.error(e);
        }
        return null;
    }
}
